/**
 * @author Gregory Banfi
 */

import org.junit._
import org.junit.Assert._
import com.meterware.servletunit.ServletRunner
import com.meterware.httpunit.PostMethodWebRequest
import com.meterware.httpunit.GetMethodWebRequest
import com.meterware.httpunit.WebRequest
import com.meterware.servletunit.ServletUnitClient
import com.meterware.httpunit.WebResponse
import sa4.FrameworkServlet
import javax.servlet.http.HttpServletResponse
import javax.servlet.http.HttpServletRequest
import sa4.MyShop
import sa4.persistence._

class testFrameworkServlet {

  //Testing the form
  val ss = new ServletRunner()
  ss.registerServlet("", classOf[FrameworkServlet].getName)
  val sp=new ServletRunner()
  sp.registerServlet("",classOf[MyShop].getName)

  @Test
  def testFormGet {
    val sc: ServletUnitClient = ss.newClient()
    val request: WebRequest = new GetMethodWebRequest("http://localhost/display")
    val response: WebResponse = sc.getResponse(request)
    assertNotNull("No response received", response)
    val xml = scala.xml.XML.loadString(response.getText)
    assertTrue((xml \\ "form" \ "@action").text == "/postComment")
  }

  @Test
  def testFormSubmit {
    val sc: ServletUnitClient = ss.newClient()

    // Ask for the form -- this installs the handler
    {
      val request: WebRequest = new GetMethodWebRequest("http://localhost/display")
      val response: WebResponse = sc.getResponse(request)
      assertNotNull("No response received", response)
      val xml = scala.xml.XML.loadString(response.getText)
      assertTrue((xml \\ "form" \ "@action").text == "/postComment")
    }

    // Submit the form.
    {
      val theAuthor = "George Orwell"
      val theQuote = "Good writer."

      val request: WebRequest = new PostMethodWebRequest("http://localhost/postComment")
      request.setParameter("author", theAuthor)
      request.setParameter("content", theQuote)

      val response: WebResponse = sc.getResponse(request)
      assertNotNull("No response received", response)
      val xml = scala.xml.XML.loadString(response.getText)
      assertTrue((xml \\ "p").text contains (theAuthor + " submitted the following comment:"))
      assertTrue((xml \\ "blockquote").text contains theQuote)
    }
  }

  @Test
  def test404 {
    val sc: ServletUnitClient = ss.newClient()
    sc.setExceptionsThrownOnErrorStatus(false)

    val request: WebRequest = new GetMethodWebRequest("http://localhost/fjklsdjdkl")
    val response: WebResponse = sc.getResponse(request)
    assertTrue(response.getResponseCode == 404)
  }

  //Testing the Routing
  @Test
  def testNotExistingRoute {
    val sv: ServletUnitClient = ss.newClient()
    sv.setExceptionsThrownOnErrorStatus(false)
    //check that no "/test" route exists
    val request: WebRequest = new GetMethodWebRequest("http://localhost/test")
    val response: WebResponse = sv.getResponse(request)
    assertTrue(response.getResponseCode == 404)
  }
  @Test
  def testAddRouteMethod {
    val sv: ServletUnitClient = ss.newClient()
    sv.setExceptionsThrownOnErrorStatus(false)
    //check that no "/test" route exists
    val request: WebRequest = new GetMethodWebRequest("http://localhost/test")
    val response: WebResponse = sv.getResponse(request)
    //add the "/test" route to the routeTable and test that now exists
    val s = new FrameworkServlet
    def f(req: HttpServletRequest, res: HttpServletResponse) = println("testing...")
    s.routing.addRoute("/test", f)
    assertNotNull("No response received", response)
  }

  @Test
  def testRemoveRoute {
    val sv: ServletUnitClient = ss.newClient()
    sv.setExceptionsThrownOnErrorStatus(false)
    //Add and then Remove /test route
    val s = new FrameworkServlet
    def f(req: HttpServletRequest, res: HttpServletResponse) = println("testing...")
    s.routing.addRoute("/test", f)
    s.routing.removeRoute("/test")
    val request: WebRequest = new GetMethodWebRequest("http://localhost/test")
    val response: WebResponse = sv.getResponse(request)
    assertTrue(response.getResponseCode == 404)
  }

  @Test
  def testClearTableMethod {
    val sv: ServletUnitClient = ss.newClient()
    sv.setExceptionsThrownOnErrorStatus(false)
    val request: WebRequest = new GetMethodWebRequest("http://localhost/test")
    val response: WebResponse = sv.getResponse(request)
    //test the clearTable method
    val s = new FrameworkServlet
    s.routing.clearRouteTable
    assertTrue(response.getResponseCode == 404)
  }
  //Testing Template

  @Test
  def testTemplate {
    val sv: ServletUnitClient = ss.newClient()
    val request: WebRequest = new GetMethodWebRequest("http://localhost/start")
    val response: WebResponse = sv.getResponse(request)
    val responseXML = (scala.xml.XML.loadString(response.getText) \\ "h1").text
    val s = new FrameworkServlet
    val xml = (s.template.loadPage("index.html") \\ "h1") .text
    assertTrue(xml.equals(responseXML)) 
  }
  
  
  //Testing Session

  @Test
  def testSession {
    val sv: ServletUnitClient = ss.newClient()
    var request: WebRequest = new GetMethodWebRequest("http://localhost/")
    var response: WebResponse = sv.getResponse(request)
    
    request= new GetMethodWebRequest("http://localhost/")
    response= sv.getResponse(request)
    
    val responseXML = (scala.xml.XML.loadString(response.getText) \\ "div").text
    Thread.sleep(5000)
    var request1: WebRequest = new GetMethodWebRequest("http://localhost/")
    var response1: WebResponse =sv.getResponse(request1)
    val responseXML1 = (scala.xml.XML.loadString(response1.getText) \\ "div").text

    assertTrue(responseXML1!=1)
   }
  
  //Testing Persistence
  @Test
  def testPersistence{
    val sv: ServletUnitClient = ss.newClient()
    var request: WebRequest = new GetMethodWebRequest("http://localhost/")
    var response: WebResponse = sv.getResponse(request)
    val s = new FrameworkServlet
    s.persistence.newAccount("foobar","1000")
    assertTrue(s.persistence.getAccounts.size==3)
    s.persistence.newAccount("hello","1000")
    assertTrue(s.persistence.getAccounts.size==4)
    s.persistence.deleteAccount("hello")
    assertTrue(s.persistence.getAccounts.size==3)
    s.persistence.updateAccount("hello", "500")
    assertTrue((s.persistence.getMouvements.toList(2) \\ "td")(1).text =="500")
    
  }
  


  
  
  
  
  
  
}
